#! /bin/bash

#  This script is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License version 2 as
#  published by the Free Software Foundation.
#
#  See the COPYING and AUTHORS files for more details.

: ${EDITOR:=vi}

# Read in library functions
if [ "$(type -t patch_file_name)" != function ]
then
	if ! [ -r $CMDPATH/scripts/patchfns ]
	then
		echo "Cannot read library $CMDPATH/scripts/patchfns" >&2
		exit 1
	fi
	. $CMDPATH/scripts/patchfns
fi

options=`getopt -o o:h --long from:,to:,cc:,bcc:,subject:,send,mbox -- "$@"`
usage()
{
	printf $"Usage: quilt mail {--mbox file|--send} [--from ...] [--to ...] [--cc ...] [--bcc ...] [--subject ...]\n"
	if [ x$1 = x-h ]
	then
		printf $"
Create mail messages from all patches in the series file, and either store
them in a mailbox file, or send them immediately. The editor is opened
with a template for the introductory message. Please see the file
%s for details.

--mbox file
	Store all messages in the specified file in mbox format. The mbox
	can later be sent using formail, for example.

--send
	Send the messages directly using %s.

--from, --subject
	The values for the From and Subject headers to use.

--to, --cc, --bcc
	Append a recipient to the To, Cc, or Bcc header.
" "/usr/share/doc/quilt-0.42/README.MAIL" "/usr/sbin/sendmail"
		exit 0
	else
		exit 1
	fi
}

msgid()
{
	local timestamp=$(date --utc "+%Y%m%d%H%M%S.%N")
	echo "$timestamp@$(hostname -f)"
}

process_mail()
{
	local tmpfile=$(gen_tempfile)

	cat > $tmpfile
	set -- $($CMDPATH/scripts/edmail --charset $opt_charset \
				  --extract-recipients To \
				  --extract-recipients Cc \
				  --extract-recipients Bcc \
				  < $tmpfile)
	if [ -n "$opt_send" ]; then
		echo /usr/sbin/sendmail "$@"
		$CMDPATH/scripts/edmail --charset $opt_charset \
				 --remove-header Bcc "$@" < $tmpfile \
		| /usr/sbin/sendmail "$@"
	else
		local from_date=$(date "+%a %b %e %H:%M:%S %Y")
		echo "From ${LOGNAME:-$(whoami)}@$(hostname -f) $from_date"
		sed -e 's/^From />From /' $tmpfile
		echo
	fi
	rm -f $tmpfile
}

options=`getopt -o h --long from:,to:,cc:,bcc:,subject: \
		     --long send,mbox:,charset: -- "$@"`

if [ $? -ne 0 ]
then
	usage
fi

eval set -- "$options"

while true
do
	case "$1" in
	--from)
		opt_from=$2
		shift 2 ;;
	--to)
		opt_to[${#opt_to[@]}]=$2
		shift 2 ;;
	--cc)
		opt_cc[${#opt_cc[@]}]=$2
		shift 2 ;;
	--bcc)
		opt_bcc[${#opt_bcc[@]}]=$2
		shift 2 ;;
	--subject)
		opt_subject=$2
		shift 2 ;;
	--send)
		opt_send=1
		shift ;;
	--mbox)
		opt_mbox=$2
		shift 2 ;;
	--charset)
		opt_charset=$2
		shift 2 ;;
	-h)
		usage -h ;;
	--)
		shift
		break ;;
	esac
done

if [ $# -gt 0 -o \( -z "$opt_send" -a -z "$opt_mbox" \) ]
then
	usage
fi
if [ -z "$opt_charset" ]; then
	case "${LC_ALL:-$LANG}" in
	*.UTF-8)
		opt_charset=UTF-8
		;;
	*)
		opt_charset=ISO-8859-15
		;;
	esac
fi

if [ "$(type -t quilt_mail_patch_filter 2> /dev/null)" != function ]; then
	quilt_mail_patch_filter() {
		echo  # We don't have a mail header
		cat
		# We could quote everything that looks like a mail
		# header instead:
		#sed -e $'s/^[\41-\176]\\+:/>&/'
	}
fi

introduction=$(gen_tempfile)
(
	cat <<-EOF
	Message-Id: <$(msgid)>
	Date: $(date --rfc-822)
	From: $opt_from
	To: $(IFS=,; echo "${opt_to[*]}")
	Cc: $(IFS=,; echo "${opt_cc[*]}")
	Bcc: $(IFS=,; echo "${opt_bcc[*]}")
	Subject-Prefix: [patch @num@/@total@]
	Subject: 

	--
	EOF
	[ -r $HOME/.signature ] && cat $HOME/.signature
) | $CMDPATH/scripts/edmail --charset $opt_charset > $introduction

$EDITOR $introduction || exit 1

set -- $(cat_series)
total=$#

if [ -n "$opt_mbox" ]; then
	exec 1> $opt_mbox
fi

subject_prefix=$(sed -ne $'s/^Subject-Prefix:[ \t]*//p' $introduction)
[ -n "$subject_prefix" ] && subject_prefix="$subject_prefix "

subject_prefix=${subject_prefix//\'/\'\'}
subject_prefix=${subject_prefix//\//\\\/}
p=${subject_prefix//@num@/$(printf %0*d ${#total} 0)}
p=${p//@total@/$total}
sed -e $'s/^\\(Subject:[ \t]\\)/\\1'"$p"'/' \
      -e '/^Subject-Prefix:/d' \
$introduction \
| $CMDPATH/scripts/edmail --charset $opt_charset \
		  --remove-empty-headers To Cc Bcc \
| process_mail

if [ -n "$opt_mbox" ]; then
	exec 1>> $opt_mbox
fi

# Remember the timestamp of the last message sent. For each message,
# increment the timestamp by one second and wait with sending until
# that time has arrived. This allows MUAs to show the messages in the
# correct order.
last_ts=$(date '+%s' -d "$(sed -ne $'s/^Date:[ \t]*//p' $introduction)")

num=1
body=$(gen_tempfile)
for patch in "$@"; do
	#echo -n '.' >&2
	# Timestamps that are a few seconds in the future don't hurt usually
	#while [ $(date '+%s') -le $last_ts ]; do
	#	sleep 1
	#done
	((last_ts++))
	new_date="$(date --rfc-822 -d "1970/01/01 UTC $last_ts seconds")"

	cat_file $(patch_file_name $patch) \
	| quilt_mail_patch_filter $patch > $body
	modify="$(awk '
	sub(/^Recipient-/, "")	{ r = gensub(/:.*/, "", "g")
				  s = gensub(/^[^:]*:[ \t]*/, "", "g")
				  gsub(/'\''/, "'\'\''", s)
				  print "--add-recipient " r "='\''" s "'\''"
				}
	sub(/^Replace-/, "")	{ r = gensub(/:.*/, "", "g")
				  s = gensub(/^[^:]*:[ \t]*/, "", "g")
				  gsub(/'\''/, "'\'\''", s)
				  print "--replace-header " r "='\''" s "'\''"
				}
	' $body)"
	p=${subject_prefix//@num@/$(printf %0*d ${#total} $num)}
	p=${p//@total@/$total}
	(	echo "Message-Id: <$(msgid)>"
		sed -e 's/^Message-Id:/References:/' \
		      -e '/^$/Q' \
		      $introduction
		echo "Content-Disposition: inline; filename=$patch"
		sed -e '/^Recipient-.*:/d' \
		      -e '/^Replace-.*:/d' \
		      -e '/^$/Q' $body
		awk '
		/^$/	{ in_body = 1 }
		in_body	{ print }
		' $body
		echo -e '\n--'
		[ -r $HOME/.signature ] && cat $HOME/.signature
	) | eval $CMDPATH/scripts/edmail --charset $opt_charset \
		--replace-header Date="\"$new_date\"" \
		To Cc Bcc \
		$modify \
	| sed -e $'s/^\\(Subject:[ \t]\\)/\\1'"$p"'/' \
		  -e '/^Subject-Prefix:/d' \
	| $CMDPATH/scripts/edmail --remove-empty-headers \
	| process_mail

	if [ ${PIPESTATUS[1]} -ne 0 ]; then
		echo "Introductory message saved as $introduction" >&2
		rm -f $body
		exit 1
	fi

	# If the character set is UTF-8, check for invalid byte
	# sequences.

	#content_length=${#body}
	#if [ -n "$(echo "$body" | tr -d '\0-\177')" ]; then
	#	charset=UTF-8
	#fi
	# Content-Transfer-Encoding: 7bit
	# Content-Transfer-Encoding: 8bit
	# Content-Type: text/plain; charset=ISO-8859-1
	# Content-Type: text/plain; charset=UTF-8

	((num++))
done
rm -f $introduction $body
#echo >&2
### Local Variables:
### mode: shell-script
### End:
# vim:filetype=sh
